package com.duoduo.admin.service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import com.duoduo.admin.api.dto.SysDeptDTO;
import com.duoduo.admin.entity.SysDept;
import com.duoduo.admin.repository.SysDeptRepository;
import com.duoduo.common.core.exception.DuoException;
import com.duoduo.common.core.exception.ErrorCode;
import com.duoduo.common.jpa.service.CommonService;
import com.duoduo.common.security.util.SecurityUtils;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import jakarta.persistence.criteria.Predicate;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class SysDeptService extends CommonService<SysDeptDTO, SysDept, Long> {

	private final SysDeptRepository sysDeptRepository;

	@Override
	public Specification<SysDept> getWhere(final SysDeptDTO request) {
		return (root, query, cb) -> {
			final List<Predicate> predicate = new ArrayList<Predicate>();
			if(request.getId()!=null) {
				predicate.add(cb.equal(root.get("id"), request.getId()));	
			}		
			
			final Predicate[] pre = new Predicate[predicate.size()];
			return query.where(predicate.toArray(pre)).getRestriction();
		};
	}

	public List<Tree<Long>> listDeptTrees() {
		return getDeptTree(sysDeptRepository.findAll(), 0L);
	}

	public List<Tree<Long>> listCurrentUserDeptTrees() {
		    Long deptId = SecurityUtils.getUser().getDeptId();
		    SysDept probe = new SysDept();
	        probe.setParentId(deptId);
	        List<SysDept> deptList = sysDeptRepository.findAll(Example.of(probe), Sort.sort(SysDept.class)
	                .by(SysDept::getId)
	                .ascending());
//	        SysDept root = new SysDept();
//	        root.setId(0L);
//	        //dtree 需要一个 -1 的父节点
//	        root.setParentId(-1L);
//	        root.setName("根目录");
//	        menus.add(root);
	        Optional<SysDept> dept = deptList.stream().filter(item -> item.getId() == deptId).findFirst();
	        return getDeptTree(deptList, dept.isPresent() ? dept.get().getParentId() : 0L);
	}


	/**
	 * 构建部门树
	 * @param depts 部门
	 * @param parentId 父级id
	 * @return
	 */
	private List<Tree<Long>> getDeptTree(List<SysDept> depts, Long parentId) {
		List<TreeNode<Long>> collect = depts.stream().filter(dept -> dept.getId().intValue() != dept.getParentId())
				.sorted(Comparator.comparingInt(SysDept::getSortOrder)).map(dept -> {
					TreeNode<Long> treeNode = new TreeNode<Long>();
					treeNode.setId(dept.getId());
					treeNode.setParentId(dept.getParentId());
					treeNode.setName(dept.getName());
					treeNode.setWeight(dept.getSortOrder());
					// 扩展属性
					Map<String, Object> extra = new HashMap<>(4);
					extra.put("createTime", dept.getCreateTime());
					treeNode.setExtra(extra);
					return treeNode;
				}).collect(Collectors.toList());
		return TreeUtil.build(collect, parentId);
	}
	
	public Boolean removeDeptById(Long id) {
		// 级联删除部门
		sysDeptRepository.deleteById(id);
		return null;
	}

	public SysDeptDTO findByName(String deptname) {
		SysDept sysDept = sysDeptRepository.findByName(deptname).orElseThrow(() ->{
			return new DuoException(ErrorCode.NOT_FIND);
		});
		SysDeptDTO dto = new SysDeptDTO();
		BeanUtils.copyProperties(sysDept, dto);
		return dto;
	}

	
	public List<Long> listChildDeptId(Long deptId) {
		    SysDept probe = new SysDept();
	        probe.setParentId(deptId);
	        List<SysDept> deptList = sysDeptRepository.findAll(Example.of(probe), Sort.sort(SysDept.class)
	                .by(SysDept::getId)
	                .ascending());
	        return deptList.stream().map(SysDept::getId).collect(Collectors.toList());
	}


}
